﻿//////////////////////////////////////////////////////////////////////////////
//
//  Copyright © 1998-2024 Glodon Company Limited.  All rights reserved.
//
//  Use of this software is subject to the terms of the Glodon license
//  agreement provided at the time of installation or download, or which
//  otherwise accompanies this software in either electronic or hard copy form.  
//
//////////////////////////////////////////////////////////////////////////////


#pragma once
#include "GnufBase.h"
#include "GnufBaseUtils.h"
#include "GnufQtObjectPtr.h"

namespace gnuf {
    class QtBalloon;
    class GNUF_BASE_EXPORT Balloon final
    {
    public:
        Balloon();
        ~Balloon();

        static Balloon * get();

        void show();
        void hide();
        bool visible() const;

        /// \brief 设置基准控件的位置和大小
        /// \details Balloon会围绕一个控件计算自身的位置，通过该方法设置基准控件的位置和大小，以便计算Balloon的弹出位置
        void setBase(int x, int y, int width, int height)
        {
            m_base.left   = x;
            m_base.top    = y;
            m_base.right  = x + width;
            m_base.bottom = y + height;
        }
        const Rect & base() const { return m_base; }

        /// \brief 设置Balloon相对于基准控件的默认位置
        /// \details 这个设置只是给gnuf提供建议，实际弹出位置需要根据Balloon大小调整，以便弹出的Balloon在屏幕内可见
        /// 例如，setPlacement(EPlacement::eAtTheBottom)后，如果发现Balloon的底端超出屏幕范围，则实际上
        /// Balloon的弹出位置会自动调整为eAtTheTop.
        void setPlacement(EPlacement val) { m_placement = val; }
        EPlacement placement() const { return m_placement; }

        /// \brief 设置Balloon的标题，会显示在Balloon的顶端，并以黑体显示，不会换行
        void setCaption(const std::wstring & v) { m_tooltip.setCaption(v); }

        /// \brief 设置Balloon的描述内容，显示在标题的下方，无黑体显示，内容过多时会进行自动换行处理
        void setDescription(const std::wstring& v) { m_tooltip.setDescription(v); }

        /// \brief 设置Balloon的解释性内容，显示在描述内容下方
        /// \details 比描述性内容更加具体详细，在ToolTip的第二阶段才会显示出来。
        /// \see setDelayToShowDetailed
        void setExplanation(const std::wstring& v) { m_tooltip.setExplanation(v); }

        /// \brief 设置Balloon的演示内容，显示在解释内容下方
        /// \details 支持图片和动图，在ToolTip的第二阶段才会显示出来。
        /// \note Qt会缓存一些资源，为提升性能。如果Dirty，将重新加载，这有性能损失，请三思。
        /// \see setDelayToShowDetailed
        /// \param v 图片或动图的资源路径
        /// \param dirty
        void setDemonstration(const std::wstring & v, bool dirty = false) {
            m_tooltip.setDemonstration(v);
            m_demonstrationDirty = dirty; // will reload it, if dirty
        }
        bool isDemonstrationDirty() const { return m_demonstrationDirty; }
        
        void setTooltip(const Tooltip & v) { m_tooltip = v; }
        const Tooltip & tooltip() const { return m_tooltip; }

        /// \brief 设置显示延时
        /// \details 在调用show一定时间后，弹出Balloon，如果设置的值小于0，则立即显示
        /// \param v 设置显示延时为v ms ，默认值为-1
        /// \see show
        void setDelayToShow(int v) { m_delayToShow = v; }
        int delayToShow() const { return m_delayToShow; }

        /// \brief 设置第二阶段显示延时
        /// \details 在Balloon弹出一定时间后，进入ToolTip的第二阶段，显示一些更详细的内容，包括解释性内容和演示内容。
        /// 如果设置的值小于0，则在弹出后立即进入第二阶段。
        /// \param v 设置显示延时为v ms 默认值为1500
        /// \see setExplanation setDemonstration
        void setDelayToShowDetailed(int v) { m_delayToShowDetailed = v; }
        int delayToShowDetailed() const { return m_delayToShowDetailed; }

        /// \brief 设置Balloon的持续时长
        /// \details 在Balloon弹出一定时间后，自动收起Balloon。如果设置的值小于0，则不自动收起，等显式调用hide后才收起。
        /// \param v 设置持续时长 v ms 默认值为-1
        void setShowHowLong(int v) { m_showHowLong = v; }
        int showHowLong() const { return m_showHowLong; }

    private:
        gcmp::QtAutoPtr<QtBalloon> m_qtBalloon;
        Rect m_base = { 0, 0, 0, 0 };
        EPlacement m_placement = EPlacement::eAtTheBottom;
        Tooltip m_tooltip;
        int m_delayToShow = -1;
        int m_showHowLong = -1;
        int m_delayToShowDetailed = 1500;
        bool m_demonstrationDirty = false;
    };
}
